package erp

import (
	"context"
	"encoding/json"
	"errors"
	"strconv"
	"strings"
	"time"

	"mall/common/utils/pointy"
	"mall/service/backend/api/internal/svc"
	"mall/service/backend/api/internal/types"
	"mall/service/backend/common/erp"
	"mall/service/product/rpc/productclient"

	// "github.com/sirupsen/logrus"
	"github.com/zeromicro/go-zero/core/logx"
)

type SyncProductStockFromErpLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

// 库存同步
func NewSyncProductStockFromErpLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SyncProductStockFromErpLogic {
	return &SyncProductStockFromErpLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *SyncProductStockFromErpLogic) SyncProductStockFromErp(req *types.SyncProductStockFromErpReq) (*types.BaseMsgResp, error) {
	var queryMaps []map[string]string
	var err error
	var path string
	if req.Ids != nil && len(*req.Ids) > 0 {
		queryMaps, err = l.syncProductStockFromErpSingle(req.Ids)
		if err != nil {
			return nil, err
		}

		// 文档地址：https://open.hupun.com/api-doc/erp/b2c/inventories/erp/single
		path = "/erp/b2c/inventories/erp/single"
		l.syncProductStockFromErp(queryMaps, path)
	} else {
		var start string
		var end string
		if req.StartTime != nil && len(strings.TrimSpace(*req.StartTime)) > 0 {
			start = *req.StartTime
		}
		if req.EndTime != nil && len(strings.TrimSpace(*req.EndTime)) > 0 {
			end = *req.EndTime
		}

		if len(start) > 0 && len(end) > 0 {
			pageSize := "50"
			var page uint64 = 1
			for {
				queryMaps := []map[string]string{{
					"end":          end,                             // 库存修改的结束时间，date格式 示例值：2023-12-10 13:45:17  string<date-time>
					"limit":        pageSize,                        // 每页条数，最大值：200 示例值：10  integer
					"page":         strconv.FormatUint(page, 10),    // 当前页，默认为1 示例值：1  integer
					"start":        start,                           // 库存修改的开始时间，date格式 示例值：2023-12-10 13:45:17  string<date-time>
					"storage_code": l.svcCtx.Config.Erp.StorageCode, // ERP中的仓库编码，默认返回所有仓库的库存  string
				}}
				// 文档地址： https://open.hupun.com/api-doc/erp/b2c/inventories/erp
				path = "/erp/b2c/inventories/erp"
				res, err := l.syncProductStockFromErpBatch(queryMaps, path)
				if err != nil {
					return nil, err
				}

				if res == 0 {
					break
				}

				page += 1
				time.Sleep(1 * time.Second)
			}
		}
	}
	if err != nil {
		return nil, err
	}

	return &types.BaseMsgResp{
		Success: true,
		Msg:     "查询ERP库存成功",
		// Msg:     l.svcCtx.Trans.Trans(l.ctx, res.Msg),
	}, nil
}

func (l *SyncProductStockFromErpLogic) syncProductStockFromErpSingle(ids *string) (items []map[string]string, err error) {
	data, err := l.svcCtx.ProductRpc.BackendGetProductList(l.ctx, &productclient.ProductListReq{
		Ids:     ids,
		WithSku: pointy.GetPointer(uint32(1)),
	})
	if err != nil {
		return nil, err
	}

	if len(data.List) > 0 {
		shopType := strconv.FormatUint(l.svcCtx.Config.Erp.ShopType, 10)
		for _, v := range data.List {
			if v.Id == nil || *v.Id == 0 {
				continue
			}

			productId := strconv.FormatUint(*v.Id, 10)
			if len(v.Skus) > 0 {
				for _, sku := range v.Skus {
					if sku.Id != nil && *sku.Id > 0 {
						items = append(items, map[string]string{
							"shop_nick":    l.svcCtx.Config.Erp.ShopNick,    // 万里牛ERP中B2C店铺昵称(掌柜旺旺/账号ID)，必须和商品推送中的店铺昵称相同  string
							"shop_type":    shopType,                        // 店铺类型，B2C平台：100  integer
							"storage_code": l.svcCtx.Config.Erp.StorageCode, // ERP中的仓库编码，默认返回所有仓库的库存  string
							"item_id":      productId,                       // 商品编号，对应商品推送中的itemID  string
							"sku_id":       strconv.FormatUint(*sku.Id, 10), // 如果商品含规格，则必填，对应商品推送的中skuID  string
						})
					}
				}
			}
		}
	}

	return
}

func (l *SyncProductStockFromErpLogic) syncProductStockFromErp(queryMaps []map[string]string, path string) (int64, error) {
	var count int64
	if len(queryMaps) > 0 {
		erpClient := erp.NewErp(l.svcCtx.Config.Erp.AppKey, l.svcCtx.Config.Erp.Secret, l.svcCtx.Config.Erp.Url, path)
		for _, v := range queryMaps {
			// logx.Infof("syncProductStockFromErp queryMap : %+v ", v)
			// map[item_id:47 shop_nick:shop1820 shop_type:100 sku_id:98 storage_code:101]
			// map[item_id:47 shop_nick:shop1820 shop_type:100 sku_id:99 storage_code:101]
			err := erpClient.GetSign(v)
			if err != nil {
				logx.Errorw("syncProductStockFromErp GetSign err", logx.Field("detail", err.Error()))
				return 0, err
			}

			resMap, err := erpClient.CallErpApi()
			if err != nil {
				logx.Errorw("syncProductStockFromErp CallErpApi err", logx.Field("detail", err.Error()))
				return 0, err
			}

			logx.Infof("syncProductStockFromErp response : %+v ", resMap)

			res := resMap["response"].(string)
			logx.Infof("syncProductStockFromErp response1 : %+v ", res)
			// [{\"storage_name\":\"默认仓库1\",\"available\":12.0000,\"quantity\":12.0000,\"storage_code\":\"101\"}]
			// []

			resp := []map[string]any{{}}
			if err = json.Unmarshal([]byte(res), &resp); err != nil {
				logx.Errorw("syncProductStockFromErp json.Unmarshal err:", logx.Field("detail", err.Error()))
				// json: cannot unmarshal array into Go value of type map[string]interface {}
				return 0, err
			}

			logx.Infof("syncProductStockFromErp response2 : %+v ", resp)

			total := int64(len(resp))
			if total == 0 {
				continue
			}

			count += total

			stockMap := map[string]uint64{}
			for _, vv := range resp {
				stockMap[v["sku_id"]] = uint64(vv["available"].(float64))
			}

			_, err = l.svcCtx.ProductRpc.UpdateProductStock(l.ctx, &productclient.UpdateProductStockReq{
				Data: stockMap,
			})
			if err != nil {
				logx.Errorw("syncProductStockFromErp UpdateProductStock Error:", logx.Field("detail", err.Error()))
				return 0, err
			}
		}
	}

	return count, nil
}

func (l *SyncProductStockFromErpLogic) syncProductStockFromErpBatch(queryMaps []map[string]string, path string) (int64, error) {
	var count int64
	if len(queryMaps) > 0 {
		erpClient := erp.NewErp(l.svcCtx.Config.Erp.AppKey, l.svcCtx.Config.Erp.Secret, l.svcCtx.Config.Erp.Url, path)
		for _, v := range queryMaps {
			// logx.Infof("syncProductStockFromErp queryMap : %+v ", v)
			// map[end:2025-01-20 00:00:00 limit:10 page:1 start:2025-01-10 00:00:00 storage_code:101]
			// map[end:2025-06-19 00:00:00 limit:50 page:1 start:2025-06-15 00:00:00 storage_code:QWZJ001]
			err := erpClient.GetSign(v)
			if err != nil {
				logx.Errorw("syncProductStockFromErp GetSign err", logx.Field("detail", err.Error()))
				return 0, err
			}

			resMap, err := erpClient.CallErpApi()
			if err != nil {
				logx.Errorw("syncProductStockFromErp CallErpApi err", logx.Field("detail", err.Error()))
				return 0, err
			}

			// logx.Infof("syncProductStockFromErp response : %+v ", resMap)
			// map[error_code:5100 error_msg:时间跨度超过7天 success:false]
			// map[response:{\"total\":3,\"inventories\":[{\"item_code\":\"chanel0001\",\"batchs\":[],\"quantity\":12.0000,\"storage_name\":\"默认仓库1\",\"oln_sku_id\":\"99\",\"oln_item_id\":\"47\",\"storage_code\":\"101\",\"available\":12.0000,\"modified\":\"2025-01-16 19:10:55\",\"sku_code\":\"LP0002\"},{\"item_code\":\"chanel0001\",\"batchs\":[],\"quantity\":15.0000,\"storage_name\":\"默认仓库1\",\"oln_sku_id\":\"100\",\"oln_item_id\":\"47\",\"storage_code\":\"101\",\"available\":15.0000,\"modified\":\"2025-01-17 15:30:20\",\"sku_code\":\"LP0003\"},{\"item_code\":\"chanel0001\",\"batchs\":[],\"quantity\":12.0000,\"storage_name\":\"默认仓库1\",\"oln_sku_id\":\"98\",\"oln_item_id\":\"47\",\"storage_code\":\"101\",\"available\":12.0000,\"modified\":\"2025-01-17 19:24:46\",\"sku_code\":\"LP0001\"}],\"page\":1} success:true]
			// map[response:{\"total\":0,\"inventories\":[],\"page\":1} success:true]
			if !resMap["success"].(bool) {
				return 0, errors.New(resMap["error_msg"].(string))
			}

			res := resMap["response"].(string)
			// logx.Infof("syncProductStockFromErp response1 : %+v ", res)
			// {\"total\":3,\"inventories\":[{\"item_code\":\"chanel0001\",\"batchs\":[],\"quantity\":12.0000,\"storage_name\":\"默认仓库1\",\"oln_sku_id\":\"99\",\"oln_item_id\":\"47\",\"storage_code\":\"101\",\"available\":12.0000,\"modified\":\"2025-01-16 19:10:55\",\"sku_code\":\"LP0002\"},{\"item_code\":\"chanel0001\",\"batchs\":[],\"quantity\":15.0000,\"storage_name\":\"默认仓库1\",\"oln_sku_id\":\"100\",\"oln_item_id\":\"47\",\"storage_code\":\"101\",\"available\":15.0000,\"modified\":\"2025-01-17 15:30:20\",\"sku_code\":\"LP0003\"},{\"item_code\":\"chanel0001\",\"batchs\":[],\"quantity\":12.0000,\"storage_name\":\"默认仓库1\",\"oln_sku_id\":\"98\",\"oln_item_id\":\"47\",\"storage_code\":\"101\",\"available\":12.0000,\"modified\":\"2025-01-17 19:24:46\",\"sku_code\":\"LP0001\"}],\"page\":1}
			// {\"total\":0,\"inventories\":[],\"page\":1}

			resp := map[string]any{}
			if err = json.Unmarshal([]byte(res), &resp); err != nil {
				logx.Errorw("syncProductStockFromErp json.Unmarshal err:", logx.Field("detail", err.Error()))
				// json: cannot unmarshal array into Go value of type map[string]interface {}
				return 0, err
			}

			// logx.Infof("syncProductStockFromErp response2 : %+v ", resp)
			// map[inventories:[map[available:12 batchs:[] item_code:chanel0001 modified:2025-01-16 19:10:55 oln_item_id:47 oln_sku_id:99 quantity:12 sku_code:LP0002 storage_code:101 storage_name:默认仓库1] map[available:15 batchs:[] item_code:chanel0001 modified:2025-01-17 15:30:20 oln_item_id:47 oln_sku_id:100 quantity:15 sku_code:LP0003 storage_code:101 storage_name:默认仓库1] map[available:12 batchs:[] item_code:chanel0001 modified:2025-01-17 19:24:46 oln_item_id:47 oln_sku_id:98 quantity:12 sku_code:LP0001 storage_code:101 storage_name:默认仓库1]] page:1 total:3]
			// map[inventories:[] page:1 total:0]

			if total := int64(resp["total"].(float64)); total == 0 {
				continue
			} else {
				count += total
			}

			stockMap := map[string]uint64{}
			for _, v := range resp["inventories"].([]any) {
				value := v.(map[string]any)
				// logx.Infof("syncProductStockFromErp response3 : %+v ", value)
				// map[available:1 batchs:[] item_code:17656 modified:2025-06-13 18:02:40 oln_item_id:2708200 oln_sku_id:610617606 quantity:1 sku_code:1765600001 storage_code:QWZJ001 storage_name:气味转角]
				if skuId, ok := value["oln_sku_id"].(string); ok {
					if availableStock, ok := value["available"].(float64); ok {
						stockMap[skuId] = uint64(availableStock)
					}
				}
			}
			_, err = l.svcCtx.ProductRpc.UpdateProductStock(l.ctx, &productclient.UpdateProductStockReq{
				Data: stockMap,
			})
			if err != nil {
				logx.Errorw("syncProductStockFromErp UpdateProductStock Error:", logx.Field("detail", err.Error()))
				return 0, err
			}
		}
	}

	return count, nil
}
